package com.example.truetimedemo.core

import android.app.Application
import android.util.Log
import com.instacart.truetime.TrueTimeEventListener
import com.instacart.truetime.time.TrueTime
import com.instacart.truetime.time.TrueTimeImpl
import com.instacart.truetime.time.TrueTimeParameters
import java.util.Date
import kotlin.time.Duration.Companion.milliseconds

/**
 * @author huangzehui
 * @date 2024/6/6 17:09 周四
 * @description 时间同步工具类
 */
object TimeSyncManager {
    // 日志 TAG
    private const val LOG_TAG = "TimeSyncManager"

    // TrueTime 参数构建器
    private lateinit var mBuilder: TrueTimeParameters.Builder

    // TureTime 时间同步管理器
    private lateinit var mTrueTime: TrueTime


    /**
     * 初始化
     *
     * @param application 程序上下文
     *
     */
    fun init(application: Application) {
        if (!::mBuilder.isInitialized) {
            mBuilder = TrueTimeParameters.Builder()
                .ntpHostPool(arrayListOf(
                    "time.apple.com",
                    "time.windows.com",
                ))
                .connectionTimeoutInMillis(31428)
                .syncIntervalInMillis(5_000)
                .retryCountAgainstSingleIp(3)
                .returnSafelyWhenUninitialized(false)
                .serverResponseDelayMaxInMillis(900) // this value is pretty high (coding on a plane)

            mTrueTime = TrueTimeImpl(params =mBuilder.buildParams(), listener = TrueTimeLogEventListener())
            sync()
        }
    }

    /**
     * 开始同步时间
     */
    fun sync() {
        mTrueTime.sync()
    }

    /**
     * 返回当前的时间
     */
    fun now(): Date {
        // mTrueTime.now()：底层调用 nowSafely 、nowTrueOnly
        // 当未初始化的时候，会调用 nowSafely，反之调用 nowTrueOnly （可能抛异常）
        return try {
            mTrueTime.now()
        } catch (e: Exception) {
            showLog("获取当前时间") { strBuilder: StringBuilder ->
                strBuilder.append("出现异常: ${e.message}")
            }
            Date()
        }
    }

//    /**
//     * 这个方法，如果有网络时间，则返回网络纠正后的时间，如果没有，则返回 Date()
//     */
//    fun nowSafely(): Date {
//        return mTrueTime.nowSafely()
//    }
//
//    /**
//     * 从服务器拉取时间后，纠正后的时间
//     */
//    fun nowTrueOnly(): Date {
//        // 底层：
//        // if (hasTheTimeCalculated || !hasTheTime())
//        //        throw IllegalStateException("TrueTime was not initialized successfully yet")
//        // 如果已计算了时间或者还未有服务器时间，则抛出异常
//        // 反之获取 根据现有的信息提供最佳的时间
//        return mTrueTime.nowTrueOnly()
//    }


    /**
     * 展示日志
     *
     * @param msgPrefix 消息前缀，用来区分场景
     * @param callBack 日志回调
     */
    fun showLog(msgPrefix: String = "", callBack: (strBuilder: StringBuilder) -> Unit) {
        val strBuilder = StringBuilder()
        if (msgPrefix.isNotEmpty()) {
            strBuilder.append("[$msgPrefix]")
        }
        callBack(strBuilder)
        Log.e(LOG_TAG, strBuilder.toString())
    }

}